<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>OCTIS - Visualize Experiments</title>
    <link href="{{ url_for('static', filename='styles/bootstrap.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='styles/styles.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='styles/slick.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='styles/slick.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='styles/slick-theme.css') }}" rel="stylesheet">
    <style type="text/css">
        html,
        body {
            margin: 0;
            padding: 0;
        }

        * {
            box-sizing: border-box;
        }


        .singleExpLink {
            display: inline-block;
            background-color: #ccd4f2;
            border-style: groove;
        }

        .singleExpLink:hover {
            background-color: #b3c2f5;
        }

        .slider {
            width: 50%;
            margin: 100px auto;
        }

        .slick-slide {
            margin: 0px 20px;
        }

        .slick-slide img {
            width: 50%;
        }

        .slick-prev:before,
        .slick-next:before {
            color: black;
        }


        .slick-slide {
            transition: all ease-in-out .3s;
            opacity: 1;
        }

        .slick-active {
            opacity: 1;
        }

        .slick-current {
            opacity: 1;
        }

        .imok {
            background-color: #ccd4f2;
        }

        .coolButtonDiv {
            border-radius: 9px;
            padding: 3px;
            border-style: groove;
        }


    </style>
    <link rel="icon" href="{{ url_for('static', filename='images/favicon.png') }}">
</head>

<body>
<div>
    <ul class="navbar">
        <li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('home') }}"><img style="width:20%"
                                                                    src="{{ url_for('static', filename='images/logo.png') }}"
                                                                    alt="alternative"></a>
        </li>
        <li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('home') }}">HOME</a>
        </li>
        <li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('CreateExperiments') }}">CREATE EXPERIMENTS</a>
        </li>
        <li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('VisualizeExperiments') }}">VISUALIZE
                EXPERIMENTS</a>
        </li>
        <li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('ManageExperiments') }}">MANAGE EXPERIMENTS</a>
        </li>
        <!--<li class="navbarEl">
            <a class="navbarLink" href="{{ url_for('serverClosed') }}">CLOSE DASHBOARD</a>
        </li>
        -->
    </ul>
</div>
<header id="header">
    <div><br>
        <h1 style="text-align: center">Visualize experiments
            <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample"
                    aria-expanded="false" aria-controls="collapseExample">
                Click here to read the instructions!
            </button>
        </h1>
    </div>
</header>

<div class="outContainer">
    <div class="container">
        <div class="row">
            <div class="col-lg-12">
                <div class="text-container">
                    <div class="collapse" id="collapseExample">
                        <div class="card card-body">
                            <p class="lead">In this page, you can <strong>compare</strong> the optimization experiments that
                                you have defined. You can compare their progress (even if they are not complete). </p>
                                <h3><span class="badge badge-primary">Quick start:</span></h3>

                            <ul>
                                <li> Select one or more batches of experiments. </li>
                                <li> Filter out the batches with respect to the dataset, model or optimized metric.  </li>
                                <li> Sort the plot of in grid by selecting the attribute for the columns and for the row.  </li>
                            </ul>
                            <br>
                            <ul>It is possible to inspect each selected experiment through two possible plots:
                                <li>a line chart which shows the evolution of the "best seen" during the optimization.</li>
                                <li>a box-plot of the all the model runs computed for each iteration.
                            </ul>
                            <br>
                            <p>Finally, for more details about an optimization experiment, you can use "click here to inspect the results"</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <br>
        <hr>
        <div class="container">
            <h4>Select one or multiple batches to analyze</h4>
        </div>
    </div>
    <section id="batchSelector" class="regular slider"></section>
    <div class="row" style="padding-left: 70%;">
        <p class="col-lg-3"><b> Line chart </b></p>

        <p id="labelGraphType"></p>
        <label class="switch">
            <input type="checkbox" id="graphType" name="graphType">
            <span class="slidercheck round"></span>
        </label>
        <p class="col-lg-3"><b> Box Plot</b></p>

    </div>

    <div id="projects">
        <div class="container">
            <div class="row">
                <h4>Filter the experiments by the following features:</h4>
            </div>
            <div class="row">
                <p>Dataset: </p>
                <div id="datasetfilters" class="button-group"></div>
            </div>
            <div class="row">
                <p>Model: </p>
                <div id="modelfilters" class="button-group"></div>
            </div>
            <div class="row">
                <p>Metric: </p>
                <div id="metricfilters" class="button-group"></div>
            </div>

            <div class="row">
                <h4>Sort the experiments by the columns and rows:</h4>
            </div>

            <div class="row">
                <p>Row:</p>
                <a id="sortRowDataset" class="button coolButtonDiv" data-what="dataset"><span>Dataset</span></a>
                <a id="sortRowModel" class="button coolButtonDiv" data-what="model"><span>Models</span></a>
                <a id="sortRowMetric" class="button coolButtonDiv" data-what="metric"><span>Metrics</span></a>
            </div>
            <div class="row">
                <p>Column:</p>
                <a id="sortColDataset" class="button coolButtonDiv" data-what="dataset"><span>Dataset</span></a>
                <a id="sortColModel" class="button coolButtonDiv" data-what="model"><span>Models</span></a>
                <a id="sortColMetric" class="button coolButtonDiv" data-what="metric"><span>Metrics</span></a>
            </div>
            <div class="row">

            </div>
            <br>
            <div class="row" style="overflow: scroll;">
                <div id="theCanvas"></div>
            </div>
        </div>
    </div>

</div>

<div class="footer">
    <div class="container">
        <h4 style="color:white;">OCTIS</h4>
        <p class="white" style="color:white;">Optimizing and Comparing Topic Models is Simple!</p>
    </div>
</div>

<script type="text/javascript" src="{{ url_for('static', filename='jquery.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='popper.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='jquery.easing.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='slick.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='plotly-latest.min.js') }}"></script>
<script>
        function getParams(vars) {
            return vars;
        }


        $(document).ready(function () {

            batchToShow = {}
            //Get batchIds
            batchIds = getParams({{ batchNames| tojson}});

        batchIds.forEach(batchId => {
            batchDiv = document.createElement("div")
            img = document.createElement("img");
            img.classList.add("img-fluid");
            img.id = batchId + "slctr";
            img.src = "{{ url_for('static', filename='images/batch.png') }}";
            img.alt = "alternative";
            img.addEventListener("click", function () {

                if (this.src.includes("selected")) {
                    n = this.src.indexOf("_selected")
                    this.src = this.src.substring(0, n).concat(".png")
                    delete batchToShow[this.id.substring(0, this.id.length - 5)]
                } else {
                    n = this.src.length - 4
                    this.src = this.src.substring(0, n).concat("_selected.png")
                    batchToShow[this.id.substring(0, this.id.length - 5)] = true;
                }
                refreshCanvas(batchToShow)

            });
            batchname = document.createElement("h4")
            batchlabel = document.createElement("span")
            batchlabel.classList.add("badge")
            batchlabel.classList.add("badge-primary")
            batchlabel.innerHTML = batchId
            batchname.appendChild(batchlabel)
            batchDiv.appendChild(img)
            batchDiv.appendChild(batchname)
            document.getElementById("batchSelector").appendChild(batchDiv)
        });


        var boxplotCheck = document.querySelector("input[name=graphType]");

        boxplotCheck.addEventListener('change', function () {
            lab = document.getElementById("labelGraphType");
            //if (this.checked) {
            //    lab.innerHTML = "<b>Boxplot</b>"
            //} else {
            //    lab.innerHTML = "<b>Line chart</b>"
            //}
            //lab.innerHTML = "<b>Boxplot / Line Chart (Best seen) </b>"
            refreshCanvas(batchToShow)
        });

        allData = ''
        var toshow = []

        var modelsSet = new Set();
        var datasetsSet = new Set();
        var metricsSet = new Set();


        function getNewExpState(batchIds) {
            $.ajax(
                {
                    type: 'POST',
                    url: "/getBatchExperiments",
                    contentType: 'application/json;charset=UTF-8',
                    dataType: 'json',
                    data: JSON.stringify({ "data": Object.keys(batchIds) }),
                    success: function (data) {
                        allData = data;
                        draw()
                    }
                })
        }

        function refreshCanvas(batchIds) {
            $.ajax(
                {
                    type: 'POST',
                    url: "/getBatchExperiments",
                    contentType: 'application/json;charset=UTF-8',
                    dataType: 'json',
                    data: JSON.stringify({ "data": Object.keys(batchIds) }),
                    success: function (data) {
                        allData = data;
                        toshow = allData;



                        data.forEach(function (item, index) {
                            modelsSet.add(item["model"]["name"])
                            datasetsSet.add(item["dataset"])
                            metricsSet.add(item["optimize_metrics"][0]["name"])
                            item["track_metrics"].forEach(function (metric, i) {
                                metricsSet.add(metric["name"])
                            });
                        });

                        modelfilterButtons = document.getElementById("modelfilters")
                        modelfilterButtons.innerHTML = '';

                        modelsSet.forEach(function (item, index) {
                            newFilter = document.createElement("a")
                            newFilter.classList.add("button")
                            newFilter.classList.add("buttonsfilters")
                            newFilter.dataset.filter = item
                            newFilter.dataset.what = "model"
                            newFilter.innerHTML = "<span>" + item + "</span>"
                            modelfilterButtons.appendChild(newFilter);
                        });


                        datasetfilterButtons = document.getElementById("datasetfilters")
                        datasetfilterButtons.innerHTML = '';

                        datasetsSet.forEach(function (item, index) {
                            newFilter = document.createElement("a")
                            newFilter.classList.add("button")
                            newFilter.classList.add("buttonsfilters")
                            newFilter.dataset.filter = item
                            newFilter.dataset.what = "dataset"
                            newFilter.innerHTML = "<span>" + item + "</span>"
                            datasetfilterButtons.appendChild(newFilter);
                        });


                        metricfilterButtons = document.getElementById("metricfilters")
                        metricfilterButtons.innerHTML = '';

                        metricsSet.forEach(function (item, index) {
                            newFilter = document.createElement("a")
                            newFilter.classList.add("button")
                            newFilter.classList.add("buttonsfilters")
                            newFilter.dataset.filter = item
                            newFilter.dataset.what = "metric"
                            newFilter.innerHTML = "<span>" + item + "</span>"
                            metricfilterButtons.appendChild(newFilter);
                        });

                        draw(data)
                    }/*success : function() {}*/
                });

        }


        $(".regular").slick({
            dots: true,
            infinite: true,
            slidesToShow: 3,
            slidesToScroll: 3
        });




        function createMatrix(div, rows, cols) {

            table = document.createElement("table");



            for (x = 0; x <= rows; x++) {

                row = document.createElement('tr')

                if (x % 2 == 0) {
                    row.style.backgroundColor = "#f5f9fc"
                } else {
                    row.style.backgroundColor = "#f5f5f5"
                }


                for (y = 0; y <= cols; y++) {

                    col = document.createElement('td')
                    col.style="text-align: center; vertical-align: middle;"

                    col.id = x.toString() + "_" + y.toString()

                    row.appendChild(col)

                }

                table.appendChild(row)
            }

            div.appendChild(table)
        }


        function fillMatrix(div, list1, list2, key1, key2, dict) {
            if (list1.length > 0 && list2.length > 0) {
                createMatrix(div, list1.length, list2.length)

                for (i = 0; i < list1.length; i++) {
                    cell = document.getElementById((i + 1).toString() + "_0")
                    cell.innerHTML = cell.innerHTML + "<h5><span class=\"badge badge-secondary\">"+
                    list1[i] + "</span></h5>"
                }

                for (i = 0; i < list2.length; i++) {
                    cell = document.getElementById("0_" + (i + 1).toString())
                    cell.innerHTML = cell.innerHTML + "<h5><span class=\"badge badge-secondary\">"+
                    list2[i] + "</span></h5>"
                }

                for (i = 0; i < dict.length; i++) {
                    row = list1.indexOf(dict[i][key1]) + 1
                    col = list2.indexOf(dict[i][key2]) + 1

                    cell = document.getElementById(row.toString() + "_" + col.toString())
                    cell.appendChild(dict[i]["div"])

                    if (document.getElementById("graphType").checked) {
                        data = []
                        for (j = 0; j < dict[i]["graph_info"][2][2].length; j++) {
                            var trace = {
                                y: dict[i]["graph_info"][2][2][j],
                                type: 'box',
                                name: j
                            }
                            data.push(trace)
                        }
                        dict[i]["graph_info"][1]["showlegend"]= false
                        dict[i]["graph_info"][1]["xaxis"]={title:"iterations"}

                        Plotly.newPlot(dict[i]["graph_info"][0], data, dict[i]["graph_info"][1]);
                    }
                    else {

                        var trace = {
                            x: dict[i]["graph_info"][2][1],
                            y: dict[i]["graph_info"][2][0],
                            type: 'scatter'
                        }
                        dict[i]["graph_info"][1]["xaxis"]={title:"Iterations"}

                        Plotly.newPlot(dict[i]["graph_info"][0], [trace], dict[i]["graph_info"][1]);
                    }


                }
            } else {
                div.innerHTML = "Select at least two parameters to sort by."
            }
        }

        var key1 = "dataset"
        var key2 = "model"

        sD = document.getElementById("sortRowDataset")
        sMod = document.getElementById("sortRowModel")
        sMet = document.getElementById("sortRowMetric")


        sCD = document.getElementById("sortColDataset")
        sCMod = document.getElementById("sortColModel")
        sCMet = document.getElementById("sortColMetric")


        sD.classList.add("imok")
        sCMod.classList.add("imok")

        sD.addEventListener("click", function () { updatekeys1("sortRowDataset") })
        sMod.addEventListener("click", function () { updatekeys1("sortRowModel") })
        sMet.addEventListener("click", function () { updatekeys1("sortRowMetric") })

        sCD.addEventListener("click", function () { updatekeys2("sortColDataset") })
        sCMod.addEventListener("click", function () { updatekeys2("sortColModel") })
        sCMet.addEventListener("click", function () { updatekeys2("sortColMetric") })

        function updatekeys1(elementId) {
            elemenet = document.getElementById(elementId)
            if (elemenet.classList.contains("imok")) {
                key1 = ""
                elemenet.classList.remove("imok")
            } else {
                key1 = elemenet.dataset.what
                if (sD.id != elemenet.id) {
                    sD.classList.remove("imok")
                }
                if (sMod.id != elemenet.id) {
                    sMod.classList.remove("imok")
                }
                if (sMet.id != elemenet.id) {
                    sMet.classList.remove("imok")
                }
                elemenet.classList.add("imok")
            }
            if (key1 == key2) {
                switch (key1) {
                    case "model":
                        sCMod.classList.remove("imok")
                        break;
                    case "dataset":
                        sCD.classList.remove("imok")
                        break;
                    case "metric":
                        sCMet.classList.remove("imok")
                        break;
                }
                key2 = ""
            }
            draw(allData)
        }

        function updatekeys2(elementId) {
            elemenet = document.getElementById(elementId)
            if (elemenet.classList.contains("imok")) {
                key2 = ""
                elemenet.classList.remove("imok")
            } else {
                key2 = elemenet.dataset.what
                if (sCD.id != elemenet.id) {
                    sCD.classList.remove("imok")
                }
                if (sCMod.id != elemenet.id) {
                    sCMod.classList.remove("imok")
                }
                if (sCMet.id != elemenet.id) {
                    sCMet.classList.remove("imok")
                }
                elemenet.classList.add("imok")
            }
            if (key1 == key2) {
                switch (key2) {
                    case "model":
                        sMod.classList.remove("imok")
                        break;
                    case "dataset":
                        sD.classList.remove("imok")
                        break;
                    case "metric":
                        sMet.classList.remove("imok")
                        break;
                }
                key1 = ""
            }
            draw(allData)
        }

        var intervalID = setInterval(function () { getNewExpState(batchToShow); }, 20000);


        function redraw(data) {

            cont = document.getElementById("theCanvas");
            cont.innerHTML = '';

            if (data != "") {



                dicFinal = []



                data.forEach(function (item, index) {
                    console.log(item)

                    innerDiv = document.createElement("div")
                    innerDiv.classList.add("element-item")
                    innerDiv.classList.add(item["model"]["name"])
                    innerDiv.style.height = "530px";
                    innerDiv.style.width = "530px";

                    a = document.createElement("a")
                    a.classList.add("popup-with-move-anim");

                    graph = document.createElement("div")
                    graph.id = item["experimentId"]

                    if (item["optimization_data"] != false) {

                        best_seen = [item["optimization_data"]["f_val"][0]]
                        second_axe = [0]



                        for (i = 1; i < item["optimization_data"]["f_val"].length; i++) {
                            if (best_seen[i - 1] < item["optimization_data"]["f_val"][i]) {
                                best_seen.push(item["optimization_data"]["f_val"][i]);
                            } else {
                                best_seen.push(best_seen[i - 1]);
                            }
                            second_axe.push(i);
                        }

                        var layout = {
                            width: 500,
                            height: 500,
                            margin: {
                                l: 50,
                                r: 50,
                                b: 40,
                                t: 40,
                                pad: 4
                            },
                            paper_bgcolor: 'rgba(256,256,256,1)'
                        };

                        ExpName = document.createElement("div")

                        heading = document.createElement("div")
                        heading.classList.add("row");
                        title = document.createElement("div")
                        title.classList.add("col-8")
                        title.innerHTML = "<button type=\"button\" class=\"btn btn-dark\" disabled><b>Batch:</b> " +
                        item["batchId"] + "</br><b> Experiment: </b>" + item["experimentId"] + "</button>"



                        col2 = document.createElement("div")
                        col2.classList.add("col-4")
                        buttonlink = document.createElement("button")
                        buttonlink.dataset.expName = item["experimentId"]
                        buttonlink.dataset.batchName = item["batchId"]
                        buttonlink.classList.add("btn")
                        buttonlink.classList.add("btn-outline-info")
                        buttonlink.innerHTML = "Click here to inspect the results"

                        buttonlink.addEventListener('click', function () {
                            location.href = "SingleExperiment/" + this.dataset.batchName + "/" + this.dataset.expName
                        });

                        heading.appendChild(title)
                        col2.appendChild(buttonlink)
                        heading.appendChild(col2)
                        ExpName.appendChild(heading)

                        innerDiv.appendChild(a);
                        a.appendChild(ExpName)
                        a.appendChild(graph);



                        dicFinal.push({
                            "model": item["model"]["name"],
                            "dataset": item["dataset"],
                            "metric": item["optimize_metrics"][0]["name"],
                            "div": innerDiv,
                            "graph_info": [
                                item["experimentId"],
                                layout,
                                [
                                    best_seen,
                                    second_axe,
                                    item["optimization_data"]["model_runs"][item["optimize_metrics"][0]["name"]]]]
                        });

                        console.log(item, index);
                    }
                });


                actModelsSet = new Set();
                actDatasetsSet = new Set();
                actMetricsSet = new Set();

                dicFinal.forEach(ele => {
                    actModelsSet.add(ele["model"])
                    actDatasetsSet.add(ele["dataset"])
                    actMetricsSet.add(ele["metric"])
                })



                if (key1 == "model") {
                    list1 = Array.from(actModelsSet)
                }
                if (key1 == "metric") {
                    list1 = Array.from(actMetricsSet)
                }
                if (key1 == "dataset") {
                    list1 = Array.from(actDatasetsSet)
                }
                if (key1 == "") {
                    list1 = []
                }

                if (key2 == "model") {
                    list2 = Array.from(actModelsSet)
                }
                if (key2 == "metric") {
                    list2 = Array.from(actMetricsSet)
                }
                if (key2 == "dataset") {
                    list2 = Array.from(actDatasetsSet)
                }
                if (key2 == "") {
                    list2 = []
                }


                fillMatrix(cont, list1, list2, key1, key2, dicFinal)


            } else {
                fillMatrix(cont, [], [], key1, key2, {})
            }
        }



        function draw() {

            var buttons = $(".button.clicked");
            if (buttons.length == 0) {
                redraw(allData)
            } else {
                all = new Set();
                for (i in allData) {
                    all.add(allData[i]["experimentId"])
                }

                toshowmetrics = new Set();
                toshowdatasets = new Set();
                toshowmodels = new Set();

                buttons.each(function () {
                    currentFilter = this.dataset.filter
                    if (this.dataset.what == "model") {
                        for (i in allData) {
                            if (allData[i]["model"]["name"] == currentFilter) {
                                toshowmodels.add(allData[i]["experimentId"])
                            }
                        }
                    }
                    if (this.dataset.what == "dataset") {
                        for (i in allData) {
                            if (allData[i]["dataset"] == currentFilter) {
                                toshowdatasets.add(allData[i]["experimentId"])
                            }
                        }
                    }
                    if (this.dataset.what == "metric") {
                        for (i in allData) {

                            if (allData[i]["optimize_metrics"][0]["name"] == currentFilter) {
                                toshowmetrics.add(allData[i]["experimentId"])
                            }
                            allData[i]["track_metrics"].forEach(function (item, index) {
                                if (item["name"] == currentFilter) toshowmetrics.add(allData[i]["experimentId"]);
                            })
                        }
                    }
                });

                if (toshowmetrics.size == 0) toshowmetrics = Array.from(all); else toshowmetrics = Array.from(toshowmetrics)
                if (toshowdatasets.size == 0) toshowdatasets = Array.from(all); else toshowdatasets = Array.from(toshowdatasets)
                if (toshowmodels.size == 0) toshowmodels = Array.from(all); else toshowmodels = Array.from(toshowmodels)

                to_show = []
                Array.from(all).forEach(ele => {
                    if (toshowmetrics.indexOf(ele) >= 0 && toshowdatasets.indexOf(ele) >= 0 && toshowmodels.indexOf(ele) >= 0)
                        to_show.push(ele)
                });

                toshow = []
                for (i in allData) {
                    if (to_show.indexOf(allData[i]["experimentId"]) >= 0) {
                        toshow.push(allData[i])
                    }
                }

                redraw(Array.from(toshow))
            }
        }


        $('.button-group').each(function (i, buttonGroup) {
            var $buttonGroup = $(buttonGroup);
            $buttonGroup.on('click', 'a', function () {
                if (this.classList.contains("clicked")) {
                    $(this).removeClass('clicked');
                } else {
                    $(this).addClass('clicked');
                }

                draw()

            });
        });


    });






</script>

</body>

</html>
